<?php


namespace app\manage\controller;


use app\common\traits\JumpReturn;
use liliuwei\think\Jump;
use think\admin\helper\TokenHelper;
use think\App;
use think\db\Query;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
use think\Validate;

abstract class Basemanage
{
    //自定义 数据返回
    use JumpReturn;

    //不是ajax 提交返回
    use Jump;

    /**
     * Request实例
     * @var \think\Request
     */
    protected $request;

    /**
     * 应用实例
     * @var \think\App
     */
    protected $app;

    /**
     * 是否批量验证
     * @var bool
     */
    protected $batchValidate = false;

    /**
     * 检测是否登录
     * @var array
     */
    protected $middleware = [];

    //请求参数
    protected $param;

    //当前域名
    protected $domain;
    // 模型
    protected $model;

    //service 层
    protected $service;

    //登录信息
    static $admin_info;

    /**
     * AdminBaseController constructor.
     * @param App $app
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function __construct(App $app)
    {
        $this->app = $app;
        $this->request = $this->app->request;

        // 控制器初始化
        $this->initialize();
    }
    /**
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author: LuckyHhy <jackhhy520@qq.com>
     * @name: initialize
     * @describe:
     */
    protected function initialize()
    {
        //用户登录信息
//        self::$admin_info=session(ADMIN_LOGIN_INFO);

        $this->initConfig();
        $this->initAssign();
        $this->initRequestConfig();
        //左侧菜单
//        $this->menuList();
    }

   /* public function index(){
        if (IS_AJAX){
            return $this->model->getAdminPageData($this->param);
        }
        return $this->fetch();
    }*/
    /**
     * @param mixed ...$vars
     * @name: assign
     * @describe:
     */
    protected function assign(...$vars){
        View::assign(...$vars);
    }


    /**
     * @param string $template
     * @return string
     * @describe:
     */
//    protected function fetch(string $template = ''){
//        return View::fetch($template);
//    }
    /**
     * 返回视图内容
     * @param string $tpl 模板名称
     * @param array $vars 模板变量
     * @param null|string $node 授权节点
     */
    protected function fetch(string $tpl = '', array $vars = [], ?string $node = null): void
    {
        foreach ($this as $name => $value) $vars[$name] = $value;
//        if ($this->csrf_state) {
//            TokenHelper::instance()->fetchTemplate($tpl, $vars, $node);
//        } else {
            throw new HttpResponseException(view($tpl, $vars));
//        }
    }
    /**
     * 初始化配置
     * @return void
     * @author Jackhhy
     */
    public function initConfig(){
        // 请求参数
        $this->param = $this->request->param();
        // 分页基础默认值
        defined('LIMIT') or define('LIMIT', isset($this->param['limit']) ? $this->param['limit'] : 20);
        defined('PAGE') or define('PAGE', isset($this->param['page']) ? $this->param['page'] : 1);
    }
    /**
     * @name: initRequestConfig
     * @describe:初始化请求配置
     */
    public function initRequestConfig(){
        // 定义是否GET请求
        defined('IS_GET') or define('IS_GET', $this->request->isGet());
        // 定义是否POST请求
        defined('IS_POST') or define('IS_POST', $this->request->isPost());
        // 定义是否AJAX请求
        defined('IS_AJAX') or define('IS_AJAX', $this->request->isAjax());
        // 定义是否PAJAX请求
        defined('IS_PJAX') or define('IS_PJAX', $this->request->isPjax());
        // 定义是否PUT请求
        defined('IS_PUT') or define('IS_PUT', $this->request->isPut());
        // 定义是否DELETE请求
        defined('IS_DELETE') or define('IS_DELETE', $this->request->isDelete());
        // 定义是否HEAD请求
        defined('IS_HEAD') or define('IS_HEAD', $this->request->isHead());
        // 定义是否PATCH请求
        defined('IS_PATCH') or define('IS_PATCH', $this->request->isPatch());
        // 定义是否为手机访问
        defined('IS_MOBILE') or define('IS_MOBILE', $this->request->isMobile());
    }
    /**
     * @name: initAssign
     * @describe:
     */
    public function initAssign()
    {
        //获取当前配置的网站地址

        //用户登录信息
//        $this->assign("_info",session(ADMIN_LOGIN_INFO));
    }
    /**
     * @param string $msg
     * @name: exception
     * @describe:
     */
    protected function exception($msg = '无法打开页面')
    {
        $this->assign(compact('msg'));
        exit($this->fetch('public/exception'));
    }


    /**
     * @return string
     * @name: makeToken
     * @describe:生成一个不会重复的字符串
     */
    public function makeToken()
    {
        $str = md5(uniqid(md5(microtime(true)), true)); //
        $str = sha1($str); //加密
        return $str;
    }

    /**
     * @param $name
     * @name: _empty
     * @describe:
     */
    public function _empty($name){
        exit($this->fetch('admin@public/404'));
    }



    /**
     * @param string $msg
     * @param int $url
     * @return \think\response\Json
     * @describe:错误提醒页面
     */
    protected function failed($msg = '哎呀…亲…您访问的页面出现错误', $url = 0)
    {
        if ($this->request->isAjax()) {
            return self::JsonReturn($msg,0,$url);
        } else {
            $this->assign(compact('msg', 'url'));
            exit($this->fetch('public/error'));
        }
    }


    /**
     * @param string $msg
     * @param int $url
     * @return \think\response\Json
     * @describe:成功提醒
     */
    protected function successed($msg = '恭喜你，提交成功！', $url = 0){
        if ($this->request->isAjax()) {
            return self::JsonReturn($msg,1,$url);
        } else {
            $this->assign(compact('msg', 'url'));
            exit($this->fetch('public/success'));
        }
    }

    /**
     * 验证数据
     * @access protected
     * @param array $data 数据
     * @param string|array $validate 验证器名或者验证规则数组
     * @param array $message 提示信息
     * @param bool $batch 是否批量验证
     * @return array|string|true
     * @throws ValidateException
     */
    protected function validate(array $data, $validate, array $message = [], bool $batch = false)
    {
        try {
            if (is_array($validate)) {
                $v = new Validate();
                $v->rule($validate);
            } else {
                if (strpos($validate, '.')) {
                    // 支持场景
                    list($validate, $scene) = explode('.', $validate);
                }
                $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
                $v = new $class();
                if (!empty($scene)) {
                    $v->scene($scene);
                }
            }

            $v->message($message);

            //是否批量验证
            if ($batch || $this->batchValidate) {
                $v->batch(true);
            }

            $result = $v->failException(false)->check($data);
            if (true !== $result) {
                return $v->getError();
            } else {
                return $result;
            }
        } catch (\Exception $e) {
            $this->error($e->getMessage());
        }
    }
    /**
     * 返回失败的操作
     * @param mixed $info 消息内容
     * @param mixed $data 返回数据
     * @param integer $code 返回代码
     */
    public function error($info, $data = '{-null-}', $code = 0): void
    {
        if ($data === '{-null-}') $data = new \stdClass();
        throw new HttpResponseException(json([
            'code' => $code, 'info' => $info, 'data' => $data,
        ]));
    }

    /**
     * 返回成功的操作
     * @param mixed $info 消息内容
     * @param mixed $data 返回数据
     * @param integer $code 返回代码
     */
    public function success($info, $data = '{-null-}', $code = 1): void
    {

        if ($data === '{-null-}') $data = new \stdClass();
        throw new HttpResponseException(json([
            'code' => $code, 'info' => $info, 'data' => $data,
        ]));
    }

    /**
     * URL重定向
     * @param string $url 跳转链接
     * @param integer $code 跳转代码
     */
    public function redirect(string $url, $code = 301): void
    {
        throw new HttpResponseException(redirect($url, $code));
    }
    /**
     * 逻辑器初始化
     * @param string|Query $dbQuery
     * @param string $template 模板名称
     * @param string $field 指定数据主键
     * @param array $where 额外更新条件
     * @param array $data 表单扩展数据
     */
    public function _form($dbQuery, string $template = '', string $field = '', array $where = [], array $data = [])
    {
        $query = is_string($dbQuery) ? $this->app->db->name($dbQuery) : $dbQuery;
        $field = $field ?: ($query->getPk() ?: 'id');
        $value = input($field, $data[$field] ?? null);
        if (IS_GET) {
            if ($value !== null) {
                $find = $query->where([$field => $value])->where($where)->find();
                if (!empty($find) && is_array($find)) $data = array_merge($data, $find);
            }
            if (false !== $this->callback('_form_filter', $data)) {
                $this->fetch($template, ['vo' => $data]);
            } else {
                return $data;
            }
        } elseif (IS_POST) {
            $data = array_merge(request()->post(), $data);
            if (false !== $this->callback('_form_filter', $data, $where)) {

                $result = $this->_save($query, $data, $field, $where) !== false;
                if (false !== $this->callback('_form_result', $result, $data)) {
                    if ($result !== false) {
                        $this->success(lang('think_library_form_success'));
                    } else {
                        $this->error(lang('think_library_form_error'));
                    }
                }
                return $result;
            }
        }
    }
    /**
     * 数据增量保存
     * @param Query|string $dbQuery 数据查询对象
     * @param array $data 需要保存的数据
     * @param string $key 更新条件查询主键
     * @param array $where 额外更新查询条件
     * @return boolean|integer 失败返回 false, 成功返回主键值或 true
     */
    protected function _save($dbQuery, array $data, string $key = 'id', array $where = [])
    {
        $val = $data[$key] ?? null;

        $query = (is_string($dbQuery) ? Db::name($dbQuery) : $dbQuery)->master()->strict(false)->where($where);
        if (empty($where[$key])) is_string($val) && strpos($val, ',') !== false ? $query->whereIn($key, explode(',', $val)) : $query->where([$key => $val]);
        return is_array($info = (clone $query)->find()) && !empty($info) ? ($query->update($data) !== false ? ($info[$key] ?? true) : false) : $query->insertGetId($data);
    }

    /**
     * 快捷删除逻辑器
     * @param string|Query $dbQuery
     * @param string $field 数据对象主键
     * @param array $where 额外更新条件
     * @return boolean|null
     * @throws DbException
     */
    protected function _delete($dbQuery, string $field = '', array $where = [])
    {
        $query = is_string($dbQuery) ? Db::name($dbQuery) : $dbQuery;
        $field = $field ?: ($query->getPk() ?: 'id');
        $value = input($field, $data[$field] ?? null);
        // 查询限制处理
        if (!empty($where)) $query->where($where);
        if (!isset($where[$field]) && is_string($value)) {
            $query->whereIn($field, explode(',', $value));
        }
        // 前置回调处理
        if (false === $this->callback('_delete_filter', $query, $where)) {
            return null;
        }
        // 阻止危险操作
        if (!$query->getOptions('where')) {
            $this->error(lang('think_library_delete_error'));
        }
        // 组装执行数据
        $data = [];
        if (method_exists($query, 'getTableFields')) {
            $fields = $query->getTableFields();
            if (in_array('deleted', $fields)) $data['deleted'] = 1;
            if (in_array('is_deleted', $fields)) $data['is_deleted'] = 1;
        }
        // 执行删除操作
        $result = (empty($data) ? $query->delete() : $query->update($data)) !== false;
        exit(json_encode($data));
        // 结果回调处理
        if (false === $this->callback('_delete_result', $result)) {
            return $result;
        }
        // 回复返回结果
        if ($result !== false) {
            $this->success(lang('think_library_delete_success'), '');
        } else {
            $this->error(lang('think_library_delete_error'));
        }
    }
    /**
     * 数据回调处理机制
     * @param string $name 回调方法名称
     * @param mixed $one 回调引用参数1
     * @param mixed $two 回调引用参数2
     * @return boolean
     */
    public function callback(string $name, &$one = [], &$two = []): bool
    {
        if (is_callable($name)) return call_user_func($name, $this, $one, $two);
        foreach (["_{$this->app->request->action()}{$name}", $name] as $method) {
            if (method_exists($this, $method) && false === $this->$method($one, $two)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 数据增量保存
     * @param Query|string $dbQuery 数据查询对象
     * @param array $data 需要保存的数据
     * @param string $key 更新条件查询主键
     * @param array $where 额外更新查询条件
     * @return boolean|integer 失败返回 false, 成功返回主键值或 true
     */
    public function save($dbQuery, array $data, string $key = 'id', array $where = [])
    {
        $val = $data[$key] ?? null;
        $query = (is_string($dbQuery) ? $this->app->db->name($dbQuery) : $dbQuery)->master()->strict(false)->where($where);
        if (empty($where[$key])) is_string($val) && strpos($val, ',') !== false ? $query->whereIn($key, explode(',', $val)) : $query->where([$key => $val]);
        return is_array($info = (clone $query)->find()) && !empty($info) ? ($query->update($data) !== false ? ($info[$key] ?? true) : false) : $query->insertGetId($data);
    }

}